package com.gmrz.webauthn.protocol.v1.json;

import com.gmrz.util.Convert;
import com.gmrz.webauthn.protocol.v1.schema.CollectedClientData;
import com.gmrz.webauthn.protocol.v1.schema.TokenBinding;
import com.gmrz.webauthn.protocol.v1.schema.TokenBindingStatus;
import com.gmrz.webauthn.protocol.v1.schema.WebOperationType;
import com.google.common.base.Strings;
import com.google.gson.*;

import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;


public class CollectedClientDataAdapter
        implements InstanceCreator<CollectedClientData>, JsonSerializer<CollectedClientData>, JsonDeserializer<CollectedClientData> {
    private static final String CHALLENGE = "challenge";
    private static final String ORIGIN = "origin";
    private static final String HASHALGORITHM = "hashAlgorithm";
    private static final String TYPE = "type";
    private static final String TOKENBINDING = "tokenBinding";
    private static final String STATUS = "status";
    private static final String ID = "id";

    public CollectedClientData deserialize(JsonElement json, Type type, JsonDeserializationContext context)
            throws JsonParseException {
        CollectedClientData clientData = new CollectedClientData();
        JsonObject jsonObject = json.getAsJsonObject();

        if (jsonObject.has("challenge")) {
            byte[] challenge = Convert.fromBase64(jsonObject.get("challenge").getAsString());
            clientData.setChallenge(challenge);
        }

        if (jsonObject.has("origin")) {
            clientData.setOrigin(jsonObject.get("origin").getAsString());
        }


        if (jsonObject.has("type")) {
            clientData.setType(
                    WebOperationType.forName(jsonObject.get("type").getAsString()));
        }

        if (jsonObject.has("tokenBinding")) {
            TokenBinding tokenBinding = new TokenBinding();

            JsonObject tokenBindingObj = jsonObject.get("tokenBinding").getAsJsonObject();
            if (tokenBindingObj.has("status")) {
                String status = tokenBindingObj.get("status").getAsString();
                if (!Strings.isNullOrEmpty(status)) {
                    tokenBinding.setStatus(TokenBindingStatus.forValue(status));
                }
            }
            if (tokenBindingObj.has("id")) {
                String id =  context.deserialize(jsonObject.get("id"), String.class);
                tokenBinding.setId(id);
            }
            clientData.setTokenBinding(tokenBinding);
        }

        return clientData;
    }


    public JsonElement serialize(CollectedClientData clientData, Type arg1, JsonSerializationContext context) {
        JsonObject clientDataObj = new JsonObject();
        String challengeEncodedStr = new String(clientData.getChallenge(), StandardCharsets.UTF_8);

        clientDataObj.addProperty("challenge", challengeEncodedStr);
        clientDataObj.addProperty("origin", clientData.getOrigin());
        clientDataObj.addProperty("hashAlgorithm", clientData.getHashAlg().getHashAlgo());
        clientDataObj.addProperty("type", clientData.getType().getOpType());
        clientDataObj.add("tokenBinding", context.serialize(clientData.getTokenBinding()));


        return clientDataObj;
    }

    public CollectedClientData createInstance(Type arg0) {
        return null;
    }
}
